/*
 * This servlet controls the registration of a user.
 */
package controllers.classes;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import models.Student;
import models.Role;
import models.User;
import classes.HibernateUtil;
import dao.UserDao;
import dao.RoleDao;
import dao.StudentDao;
import javax.servlet.RequestDispatcher;
import org.hibernate.Session;
import classes.Mail;
import classes.Password;
import dao.ActivationDao;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSession;
import models.Activation;

/**
 *
 * @author Achie
 */
public class RegisterController extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/register.jsp");
        dispatcher.forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, MalformedURLException {
        try {
            //Do the login or registration
            performRegistration(request, response);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(RegisterController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void performRegistration(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, MalformedURLException, NoSuchAlgorithmException {
        //------------------------------------------------------------------
        //Get values from the registration form
        //------------------------------------------------------------------
        ArrayList<String> members = new ArrayList<String>();

        long id = System.nanoTime();
        String password = request.getParameter("password");
        String confirmpassword = request.getParameter("confirmpassword");
        String email = request.getParameter("email");
        String firstname = request.getParameter("firstname");
        String insertion = request.getParameter("insertion");
        String lastname = request.getParameter("lastname");
        String interests = request.getParameter("interests");
        Role role = null;

        //Trim fields (except the ones that need a space)
        email = email.trim();
        password = password.trim();
        confirmpassword = confirmpassword.trim();
        firstname = firstname.trim();
        insertion = insertion.trim();
        lastname = lastname.trim();

        //Add values to the array, to scan the fields easier.
        members.add(password);
        members.add(confirmpassword);
        members.add(email);
        members.add(firstname);
        //members.add(insertion);
        members.add(lastname);

        //------------------------------------------------------------------
        //Check whether all fields are correctly inserted!
        //------------------------------------------------------------------
        Map<String, String> errors = new HashMap<String, String>();

        if (!email.contains("@")) { //If the email field doesn't contain @
            errors.put("email", "Your email is not correct");
        }

        if (!emailAvailable(email)) {
            errors.put("email", "Email does already exists");
        }

        if (!password.equals(confirmpassword)) { //Check password and confirm password equalance, if not 
            errors.put("confirm", "Passwords did not match");
        }

        if (!password.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\\S+$).{6,32}$")) { //Check password size and regex, if invalid
            errors.put("password", "Must contain: [a-z] [A-Z] [0-9]");
        }

        if (firstname.matches(".*\\d.*")) {
            errors.put("firstname", "Firstname cannot contain digits");
        }

        if (insertion.matches(".*\\d.*")) {
            errors.put("insertion", "Insertion cannot contain digits");
        }

        if (lastname.matches(".*\\d.*")) {
            errors.put("lastname", "Lastname cannot contain digits");
        }

        // Handling the errors...
        if (!errors.isEmpty()) {
            request.setAttribute("error", errors);
            request.getRequestDispatcher("jsp/register.jsp").forward(request, response);
            return;
        }

        HibernateUtil hu = new HibernateUtil();
        Session ses = hu.openSession();

        //create a new user object
        UserDao ud = new UserDao(ses);
        User userst = new User(id, email, password, firstname, insertion, lastname);
        userst.setDate();
        ud.save(userst);

        //create a new student object
        StudentDao sd = new StudentDao(ses);
        Student student = new Student(id, userst, firstname, lastname, insertion, interests);
        boolean is_saved = sd.save(student);

        //------------------------------------------------------------------
        //The following code checks if the member is successfully saved and inserted in the database.
        //------------------------------------------------------------------
        if (is_saved) { //if saved succesfully
            HttpSession s = request.getSession();
            s.setAttribute("sesregSucses", "true");
            sendVerificationEmail(email, student); //send verification mail
        }
        hu.close(); //close connection
        response.sendRedirect("jsp/register.jsp"); //redirect to the register page
    }

    /**
     *
     * this method sends an activation e-mail to the user
     *
     * @param email - email of the user
     * @param student - student object
     * @throws MalformedURLException
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public void sendVerificationEmail(String email, Student student) throws MalformedURLException, IOException, NoSuchAlgorithmException {
        Password p = new Password(email);
        String studid = "" + student.getId();
        String activationKey = p.bytesToStringForSha(p.createSHAbyte(email)) + studid; //encrypt email and id sha1

        //-------------------------------------------------------------
        //Save verification to database
        //-------------------------------------------------------------
        HibernateUtil hu = new HibernateUtil();
        ActivationDao ad = new ActivationDao(hu.openSession());
        long id = System.nanoTime();
        Activation activation = new Activation(id, activationKey);
        activation.setStudent(student);
        boolean y = ad.save(activation);

        String fullname = (student.getFirstname() + " " + student.getInsertion() + " " + student.getLastname()).trim();
        String[][] keys = {
            {"key", activationKey},
            {"user", fullname.replaceAll(" ", "%20")}
        };
        String message = Mail.setMessage("http://localhost:8080/Project_PDL_Test/jsp/mail/verify_account.jsp", keys);
        try {
            Mail.sendMail(email, fullname, "Verify your account", message);
        } catch (Exception ex) {
        }
    }

    /*
     * redirect method
     */
    public void goToRegister(HttpServletResponse response) throws IOException { 
        response.sendRedirect("jsp/register.jsp");
    }

    /**
     * this method checks whether the inserted e-mail is available
     * @param email of the user
     * @return 
     */
    public boolean emailAvailable(String email) {
        HibernateUtil hu = new HibernateUtil();
        UserDao md = new UserDao(hu.openSession());
        md.findAllByEmail(email);
        if (md.findAllByEmail(email).size() > 0) { //if email already exist (higher than 1)
            return false;
        } else {
            return true;
        }
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
